package interpreter

import (
	"parse/src/configs"
	"parse/src/constants"
	"parse/src/nodes"
	"parse/src/token"
	"parse/src/utils"
)

type Interpreter struct {
}

func NewInterpreter() *Interpreter {
	temp := &Interpreter{}
	return temp
}

// 处理得到的结果
func DealResult(result *RTResult, err *Error) {
	switch configs.GetConfig("TESTTYPE") {
	case 1:
		if result != nil {
			// 输出得到的结果
			if result.Value != nil {
				for _, v := range result.Value.(*List).Elements {
					if v != nil {
						s := utils.GetItemAttribute(v, "Value")
						if s != nil {
							utils.Println(s)
							continue
						}
						e := utils.GetItemAttribute(v, "Elements")
						if e != nil {
							s := e.([]interface{})
							for _, value := range s {
								if value != nil {
									value_ := utils.GetItemAttribute(value, "Value")
									utils.Println(value_)
								}
							}
							continue
						}
					}
				}
			}
			if result.Error_ != nil {
				utils.PrintErr(result.Error_.ToString())
			}
		}
		if err != nil {
			utils.PrintErr(err.ToString())
		}
	case 2:
		if result != nil {
			// 输出得到的结果
			if result.Value != nil {
				for _, v := range result.Value.(*List).Elements {
					if v != nil {
						s := utils.GetItemAttribute(v, "Value")
						if s != nil {
							utils.Println(s)
							continue
						}
						e := utils.GetItemAttribute(v, "Elements")
						if e != nil {
							s := e.([]interface{})
							for _, value := range s {
								value_ := utils.GetItemAttribute(value, "Value")
								utils.Println(value_)
							}
							continue
						}
					}
				}
			}
			if result.Error_ != nil {
				utils.PrintErr(result.Error_.ToString())
			}
		}
		if err != nil {
			utils.PrintErr(err.ToString())
		}
	}
}

// 处理解析文件得到的结果
func DealFileResult(result *RTResult, err *Error) {
	switch configs.GetConfig("TESTTYPE") {
	case 1:
		if err != nil {
			utils.PrintErr(err.ToString())
		}
	case 2:
		if err != nil {
			utils.PrintErr(err.ToString())
		}
	}
}

// 开始运行程序，这里是运行总节点的入口函数
func (i *Interpreter) Visit(node interface{}, context *Context) *RTResult {
	if node == nil {
		return i.VisitDefault()
	}
	// 得到需要访问的函数的名字
	// 利用反射的方式，得到需要运行的函数
	methodName := "Visit" + utils.GetTypeName(node, true)
	// 此处 i 必须是地址
	value := utils.RunFunc(&i, methodName, node, context)
	if value == nil {
		return i.VisitDefault()
	}
	return value.(*RTResult)
}

// 开始运行程序，这里是运行总节点的入口函数
func (i *Interpreter) VisitDefault() *RTResult {
	p := &token.Position{
		Idx:   0,
		Ln:    0,
		Col:   0,
		Fn:    "编译器内部文件",
		FText: "编译器内部错误",
	}
	return &RTResult{
		Value: nil,
		Error_: &Error{
			PosStart:  p,
			PosEnd:    p,
			ErrorName: "内部错误",
			Details:   "原因go文件中的VisitDefault方法不存在",
		},
		FuncReturnValue:    nil,
		LoopShouldContinue: false,
		LoopShouldBreak:    false,
	}
}

// 运行number节点
func (i *Interpreter) VisitNumberNode(node *nodes.NumberNode, context *Context) *RTResult {
	value := node.Tok.Value
	baseNode := node.BaseNode
	temp := NewNumber(value)
	temp.SetContext(context).SetPos(baseNode.PosStart, baseNode.PosEnd)
	return NewRTResult().Success(temp)
}

// 运行 string 节点
func (i *Interpreter) VisitStringNode(node *nodes.StringNode, context *Context) *RTResult {
	value := node.Tok.Value
	baseNode := node.BaseNode
	res := NewRTResult()
	newString := NewString(value.(string))
	newString.SetContext(context).SetPos(baseNode.PosStart, baseNode.PosEnd)
	return res.Success(newString)
}

// 运行 list 节点
func (i *Interpreter) VisitListNode(node *nodes.ListNode, context *Context) *RTResult {
	res := NewRTResult()
	var elements []interface{}

	for _, v := range node.ElementNodes {
		temp := res.Register(i.Visit(v, context))
		elements = append(elements, temp)
		if res.ShouldReturn() != nil {
			return res
		}
	}

	baseNode := node.BaseNode
	t := NewList(elements)
	t.SetContext(context).SetPos(baseNode.PosStart, baseNode.PosEnd)
	return res.Success(t)
}

// 运行 变量access 节点
func (i *Interpreter) VisitVarAccessNode(node *nodes.VarAccessNode, context *Context) *RTResult {
	res := NewRTResult()
	varName := node.VarNameTok.Value.(string)
	value := context.SymbolTable.Get(varName)

	if value == nil { // 变量没有被分配
		return res.Failure(NewError(node.PosStart, node.PosEnd, "语法错误", "该 "+varName+" 函数或者变量不存在"))
	}

	/***********这里代码貌似有问题，后期再调试**************/
	builtInFunction, err := value.(*BuiltInFunction)
	if err { // 表示没有错误，就是这个对象
		baseNode := node.BaseNode
		value = builtInFunction.Copy()
		value.(*BuiltInFunction).SetPos(baseNode.PosStart, baseNode.PosEnd)
	}

	return res.Success(value)
}

// 运行 变量 assign 节点
func (i *Interpreter) VisitVarAssignNode(node *nodes.VarAssignNode, context *Context) *RTResult {
	res := NewRTResult()
	varName := node.VarNameTok.Value.(string)
	value := res.Register(i.Visit(node.VarValueNode, context))
	if res.Error_ != nil {
		return res
	}

	context.SymbolTable.Set(varName, value)
	return res.Success(value)
}

// 运行 binOp （a + b 类似的） 节点
func (i *Interpreter) VisitBinOpNode(node *nodes.BinOpNode, context *Context) *RTResult {
	res := NewRTResult()
	left := res.Register(i.Visit(node.LeftNode, context))
	if res.ShouldReturn() != nil {
		return res
	}
	right := res.Register(i.Visit(node.RightNode, context))
	if res.ShouldReturn() != nil {
		return res
	}

	var result_ interface{}
	var error_ *RTError
	if node.OpTok.Type_ == constants.TT_PLUS {
		result_, error_ = left.(*Number).AddedTo(right.(*Number))
	} else if node.OpTok.Type_ == constants.TT_MINUS {
		result_, error_ = left.(*Number).SubbedBy(right.(*Number))
	} else if node.OpTok.Type_ == constants.TT_MUL {
		result_, error_ = left.(*Number).MultedBy(right.(*Number))
	} else if node.OpTok.Type_ == constants.TT_DIV {
		result_, error_ = left.(*Number).DivedBy(right.(*Number))
	} else if node.OpTok.Type_ == constants.TT_YU {
		result_, error_ = left.(*Number).YuedBy(right.(*Number))
	} else if node.OpTok.Type_ == constants.TT_POW {
		result_, error_ = left.(*Number).PowedBy(right.(*Number))
	} else if node.OpTok.Type_ == constants.TT_EE {
		result_, error_ = left.(*Number).GetComparisonEq(right.(*Number))
	} else if node.OpTok.Type_ == constants.TT_NE {
		result_, error_ = left.(*Number).GetComparisonNe(right.(*Number))
	} else if node.OpTok.Type_ == constants.TT_LT {
		result_, error_ = left.(*Number).GetComparisonNe(right.(*Number))
	} else if node.OpTok.Type_ == constants.TT_GT {
		result_, error_ = left.(*Number).GetComparisonGt(right.(*Number))
	} else if node.OpTok.Type_ == constants.TT_LTE {
		result_, error_ = left.(*Number).GetComparisonLte(right.(*Number))
	} else if node.OpTok.Type_ == constants.TT_GTE { // 以上就是通过字符来匹配的
		result_, error_ = left.(*Number).GetComparisonGte(right.(*Number))
	} else if node.OpTok.MatcheKeyword("AND") { // 以下就是通过关键字匹配的
		result_, error_ = left.(*Number).AndedBy(right.(*Number))
	} else if node.OpTok.MatcheKeyword("OR") {
		result_, error_ = left.(*Number).OredBy(right.(*Number))
	}
	if error_ != nil {
		return res.Failure(error_.Error)
	}
	result_.(*Number).SetPos(node.PosStart, node.PosEnd)
	return res.Success(result_)
}

// 运行一元方程节点
func (i *Interpreter) VisitUnaryOpNode(node *nodes.UnaryOpNode, context *Context) interface{} {
	res := NewRTResult()
	number := res.Register(i.Visit(node.Node, context)).(*Number)

	if res.ShouldReturn() != nil {
		return res
	}

	var temp interface{}
	var error_ *RTError

	if node.OpTok.Type_ == constants.TT_MINUS {
		temp, error_ = number.MultedBy(NewNumber(float64(-1)))
		number = temp.(*Number)
	} else if node.OpTok.MatcheKeyword("NOT") {
		temp, error_ = number.NotedBy()
		number = temp.(*Number)
	}

	if error_ != nil {
		return res.Failure(error_.Error)
	} else {
		number.SetPos(node.PosStart, node.PosEnd)
		return res.Success(number)
	}
}

// 运行if节点
func (i *Interpreter) VisitIfNode(node *nodes.IfNode, context *Context) interface{} {
	res := NewRTResult()

	for _, v := range node.Cases {
		condition := v.Condition
		expr := v.Expr
		shouldReturnNull := v.ShouldReturnNull
		conditionValue := res.Register(i.Visit(condition, context)).(*Number)
		if res.ShouldReturn() != nil {
			return res
		}
		if conditionValue.IsTrue() {
			exprValue := res.Register(i.Visit(expr, context))
			if res.ShouldReturn() != nil {
				return res
			}
			var res_ interface{}
			if shouldReturnNull {
				res_ = Null
			} else {
				res_ = exprValue
			}
			return res.Success(res_)
		}
	}

	// 运行elseCase
	if node.ElseCase != nil {
		expr := node.ElseCase.Expr
		shouldReturnNull := node.ElseCase.ShouldReturnNull
		exprValue := res.Register(i.Visit(expr, context))
		if res.ShouldReturn() != nil {
			return res
		}
		// 判断是否有返回null值，有返回null值就返回 null
		var res_ interface{}
		if shouldReturnNull {
			res_ = Null
		} else {
			res_ = exprValue
		}
		return res.Success(res_)
	}
	return res.Success(Null)
}

// 运行 for 节点
func (i *Interpreter) VisitForNode(node *nodes.ForNode, context *Context) interface{} {
	res := NewRTResult()
	var elements []interface{}

	startValue := res.Register(i.Visit(node.StartValueNode, context)).(*Number)
	if res.ShouldReturn() != nil {
		return res
	}

	endValue := res.Register(i.Visit(node.EndValueNode, context)).(*Number)
	if res.ShouldReturn() != nil {
		return res
	}

	var stepValue *Number
	if node.StepValueNode != nil {
		stepValue = res.Register(i.Visit(node.StepValueNode, context)).(*Number)
		if res.ShouldReturn() != nil {
			return res
		}
	} else { // 默认情况下是每步为1s
		stepValue = NewNumber(float64(1))
	}

	startValue_ := startValue.Value.(float64)

	var condition = func() bool {
		return false
	}
	// 判断步数是否大于0,创建一个匿名函数
	if stepValue.Value.(float64) >= 0 {
		condition = func() bool {
			return startValue_ < endValue.Value.(float64)
		}
	} else {
		condition = func() bool {
			return startValue_ > endValue.Value.(float64)
		}
	}

	for condition() {
		context.SymbolTable.Set(node.VarNameToken.Value.(string), NewNumber(startValue_))
		startValue_ += stepValue.Value.(float64)

		value := res.Register(i.Visit(node.BodyNode, context))
		if res.ShouldReturn() != nil && res.LoopShouldContinue == false && res.LoopShouldBreak == false {
			return res
		}

		if res.LoopShouldContinue {
			continue
		}

		if res.LoopShouldBreak {
			break
		}

		elements = append(elements, value)
	}
	var res_ interface{}
	if node.ShouldReturnNull {
		res_ = Null
	} else {
		l := NewList(elements)
		l.SetContext(context).SetPos(node.PosStart, node.PosEnd)
		res_ = l
	}
	return res.Success(res_)
}

// 运行 while 节点
func (i *Interpreter) VisitWhileNode(node *nodes.WhileNode, context *Context) interface{} {
	res := NewRTResult()
	var elements []interface{}

	for true {
		condition := res.Register(i.Visit(node.ConditionNode, context)).(*Number)
		if res.ShouldReturn() != nil {
			return res
		}
		if !condition.IsTrue() {
			break
		}
		register := res.Register(i.Visit(node.BodyNode, context))
		if res.Error_ != nil {
			return res
		}
		if register == nil {
			continue
		}
		value, ok := register.(*Number)
		if !ok {
			return res
		}
		if res.ShouldReturn() != nil && res.LoopShouldContinue && res.LoopShouldBreak {
			return res
		}

		if res.LoopShouldContinue {
			continue
		}
		if res.LoopShouldBreak {
			break
		}
		elements = append(elements, value)
	}
	var res_ interface{}
	if node.ShouldReturnNull != nil {
		res_ = Null
	} else {
		res_ = NewList(elements).SetContext(context).SetPos(node.PosStart, node.PosEnd)
	}
	return res.Success(res_)
}

// 运行 funcdefNode 节点
func (i *Interpreter) VisitFuncDefNode(node *nodes.FuncDefNode, context *Context) interface{} {

	res := NewRTResult()

	// 得到函数的名称
	var funcName string
	if node.VarNameTok != nil {
		funcName = node.VarNameTok.Value.(string)
	} else {
		funcName = ""
	}

	// 得到函数体
	bodyNode := node.BodyNode

	// 得到参数名字
	var argNames []string
	for _, argName := range node.ArgNameToks {
		argNames = append(argNames, argName.Value.(string))
	}

	// 计算出函数值
	funcValue := NewFunction(funcName, bodyNode, argNames, node.ShouldAutoReturn)

	// 当拿到的变量名字token不是空的话，就将该函数保存到上下文的 符号表中
	if node.VarNameTok != nil {
		context.SymbolTable.Set(funcName, funcValue)
	} else {
		return funcValue.Execute(nil)
	}

	return res.Success(funcValue)
}

// 运行 callNode 节点
func (i *Interpreter) VisitCallNode(node *nodes.CallNode, context *Context) interface{} {
	res := NewRTResult()
	var args []interface{}

	temp := res.Register(i.Visit(node.NodeToCall, context))

	var valueToCall interface{}
	switch temp.(type) {
	case *Function: // 为Function
		valueToCall = temp.(*Function) // 普通函数，也有可能是系统函数
	case *BuiltInFunction: // 为BuiltInFunction
		valueToCall = temp.(*BuiltInFunction) // 普通函数，也有可能是系统函数
	default:
		return res
	}

	if res.ShouldReturn() != nil {
		return res
	}

	copy_ := utils.RunFuncOther(valueToCall, "Copy")

	if copy_ == nil {
		res.Error_ = NewError(node.PosStart, node.PosEnd, "运行出错", "对象拷贝时出错")
		return res
	}

	utils.RunFuncOther(copy_, "SetPos", node.PosStart, node.PosEnd)

	for _, argNode := range node.ArgNodes {
		args = append(args, res.Register(i.Visit(argNode, context)))
		if res.ShouldReturn() != nil {
			return res
		}
	}

	returnValue := res.Register(utils.RunFuncOther(valueToCall, "Execute", args).(*RTResult))
	if returnValue == nil { // 表示不需要返回的
		return res.Success(nil)
	}
	if res.ShouldReturn() != nil {
		return res
	}

	copy__ := utils.RunFuncOther(returnValue, "Copy")

	_ = utils.RunFuncOther(copy__, "SetPos", node.PosStart, node.PosEnd)

	_ = utils.RunFuncOther(copy__, "SetContext", context)

	return res.Success(copy__)

}

// 运行 returnNode 节点
func (i *Interpreter) VisitReturnNode(node *nodes.ReturnNode, context *Context) interface{} {
	res := NewRTResult()

	var value interface{}
	if node.NodeToReturn != nil {
		value = res.Register(i.Visit(node.NodeToReturn, context))
		if res.ShouldReturn() != nil {
			return res
		}
	} else {
		value = Null
	}

	return res.SuccessReturn(value)
}

// 运行 continue 节点
func (i *Interpreter) VisitContinueNode(node *nodes.ReturnNode, context *Context) interface{} {
	res := NewRTResult()

	return res.SuccessContinue(nil)
}

// 运行 break 节点
func (i *Interpreter) VisitBreakNode(node *nodes.ReturnNode, context *Context) interface{} {
	res := NewRTResult()

	return res.SuccessBreak(nil)
}
